package zhongjie;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

// 中介者接口
interface ChatMediator {
    void registerMember(Member member);
    void sendTextMessage(Member sender, String receiverId, String message);
    void sendImageMessage(Member sender, String receiverId, byte[] imageData);
}

// 会员接口
interface Member {
    String getId();
    void receiveTextMessage(String senderId, String message);
    void receiveImageMessage(String senderId, byte[] imageData);
    void sendTextMessage(String receiverId, String message);
    void sendImageMessage(String receiverId, byte[] imageData);
}

// 普通会员实现
class CommonMember implements Member, Runnable {
    private String id;
    private ChatMediator chatMediator;
    Socket socket;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private boolean running = true;

    public CommonMember(String id, Socket socket, ChatMediator chatMediator) {
        this.id = id;
        this.socket = socket;
        this.chatMediator = chatMediator;
        try {
            out = new ObjectOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());
            new Thread(this).start(); // 启动消息接收线程
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void receiveTextMessage(String senderId, String message) {
        try {
            out.writeObject(new Message(Message.TEXT, senderId, id, message));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void receiveImageMessage(String senderId, byte[] imageData) {
        System.out.println("普通会员不能接收图片消息");
    }

    @Override
    public void sendTextMessage(String receiverId, String message) {
        chatMediator.sendTextMessage(this, receiverId, message);
    }

    @Override
    public void sendImageMessage(String receiverId, byte[] imageData) {
        System.out.println("普通会员不能发送图片消息");
    }

    @Override
    public void run() {
        try {
            while (running) {
                Object obj = in.readObject();
                if (obj instanceof Message) {
                    Message msg = (Message) obj;
                    if (msg.getType() == Message.REGISTER) {
                        chatMediator.registerMember(this);
                        System.out.println("会员 " + id + " 已注册到聊天室");
                    } else if (msg.getType() == Message.TEXT) {
                        sendTextMessage(msg.getReceiverId(), msg.getContext());
                    } else if (msg.getType() == Message.IMAGE) {
                        System.out.println("普通会员无法处理图片消息");
                    }
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            if (running) {
                System.out.println("会员 " + id + " 已断开连接");
                disconnect();
            }
        }
    }

    public void disconnect() {
        running = false;
        try {
            if (in != null) in.close();
            if (out != null) out.close();
            if (socket != null) socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 钻石会员实现
class DiamondMember implements Member, Runnable {
    private String id;
    private ChatMediator chatMediator;
    private Socket socket;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private boolean running = true;
    private static final int MAX_IMAGE_SIZE = 1024 * 1024; // 1MB

    public DiamondMember(String id, Socket socket, ChatMediator chatMediator) {
        this.id = id;
        this.socket = socket;
        this.chatMediator = chatMediator;
        try {
            out = new ObjectOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());
            new Thread(this).start(); // 启动消息接收线程
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void receiveTextMessage(String senderId, String message) {
        try {
            out.writeObject(new Message(Message.TEXT, senderId, id, message));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void receiveImageMessage(String senderId, byte[] imageData) {
        try {
            if (imageData.length <= MAX_IMAGE_SIZE) {
                out.writeObject(new Message(Message.IMAGE, senderId, id, imageData));
            } else {
                out.writeObject(new Message(Message.ERROR, "系统", id, "图片大小超过限制"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void sendTextMessage(String receiverId, String message) {
        chatMediator.sendTextMessage(this, receiverId, message);
    }

    @Override
    public void sendImageMessage(String receiverId, byte[] imageData) {
        chatMediator.sendImageMessage(this, receiverId, imageData);
    }

    @Override
    public void run() {
        try {
            while (running) {
                Object obj = in.readObject();
                if (obj instanceof Message) {
                    Message msg = (Message) obj;
                    if (msg.getType() == Message.REGISTER) {
                        chatMediator.registerMember(this);
                        System.out.println("钻石会员 " + id + " 已注册到聊天室");
                    } else if (msg.getType() == Message.TEXT) {
                        sendTextMessage(msg.getReceiverId(), msg.getContext());
                    } else if (msg.getType() == Message.IMAGE) {
                        sendImageMessage(msg.getReceiverId(), (byte[]) msg.getContent());
                    }
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            if (running) {
                System.out.println("会员 " + id + " 已断开连接");
                disconnect();
            }
        }
    }

    public void disconnect() {
        running = false;
        try {
            if (in != null) in.close();
            if (out != null) out.close();
            if (socket != null) socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 聊天服务器实现
class ChatServer implements ChatMediator {
    private Map<String, Member> members;
    private ContentFilter filter;
    private ServerSocket serverSocket;
    private ExecutorService threadPool;
    private boolean running = true;
    private static final int PORT = 8888;
    private static final int THREAD_POOL_SIZE = 10;

    public ChatServer() {
        members = new ConcurrentHashMap<>();
        filter = new ContentFilter();
        try {
            serverSocket = new ServerSocket(PORT);
            threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
            System.out.println("聊天室服务器已启动，监听端口: " + PORT);
            startAcceptingConnections();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void startAcceptingConnections() {
        new Thread(() -> {
            while (running) {
                try {
                    Socket clientSocket = serverSocket.accept();
                    threadPool.execute(() -> handleClient(clientSocket));
                } catch (IOException e) {
                    if (running) {
                        System.out.println("接受客户端连接时出错: " + e.getMessage());
                    }
                }
            }
        }).start();
    }

    private void handleClient(Socket clientSocket) {
        try {
            ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
            Message msg = (Message) in.readObject();
            
            if (msg.getType() == Message.REGISTER) {
                String memberId = msg.getSenderId();
                String memberType = (String) msg.getContent();
                
                Member member;
                if ("diamond".equalsIgnoreCase(memberType)) {
                    member = new DiamondMember(memberId, clientSocket, this);
                } else {
                    member = new CommonMember(memberId, clientSocket, this);
                }
                
                members.put(memberId, member);
                System.out.println("新会员 " + memberId + " 已连接，类型: " + memberType);
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void registerMember(Member member) {
        members.put(member.getId(), member);
    }

    @Override
    public void sendTextMessage(Member sender, String receiverId, String message) {
        String filteredMessage = filter.filterText(message);
        Member receiver = members.get(receiverId);
        if (receiver != null) {
            receiver.receiveTextMessage(sender.getId(), filteredMessage);
            System.out.println("文本消息从 " + sender.getId() + " 发送到 " + receiverId);
        } else {
            System.out.println("接收者 " + receiverId + " 不存在");
        }
    }

    @Override
    public void sendImageMessage(Member sender, String receiverId, byte[] imageData) {
        if (filter.isImageSizeValid(imageData)) {
            Member receiver = members.get(receiverId);
            if (receiver != null) {
                receiver.receiveImageMessage(sender.getId(), imageData);
                System.out.println("图片消息从 " + sender.getId() + " 发送到 " + receiverId);
            } else {
                System.out.println("接收者 " + receiverId + " 不存在");
            }
        } else {
            System.out.println("图片大小超过限制，发送失败");
            try {
                ObjectOutputStream out = new ObjectOutputStream(((CommonMember)sender).socket.getOutputStream());
                out.writeObject(new Message(Message.ERROR, "系统", sender.getId(), "图片大小超过限制"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void shutdown() {
        running = false;
        threadPool.shutdown();
        try {
            if (!serverSocket.isClosed()) {
                serverSocket.close();
            }
            for (Member member : members.values()) {
                if (member instanceof CommonMember) {
                    ((CommonMember) member).disconnect();
                } else if (member instanceof DiamondMember) {
                    ((DiamondMember) member).disconnect();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 内容过滤器
class ContentFilter {
    private static final List<String> INAPPROPRIATE_WORDS = Arrays.asList("垃圾", "笨蛋", "傻瓜");

    public String filterText(String text) {
        String filteredText = text;
        for (String word : INAPPROPRIATE_WORDS) {
            filteredText = filteredText.replaceAll(word, "***");
        }
        return filteredText;
    }

    public boolean isImageSizeValid(byte[] imageData) {
        return imageData.length <= 1024 * 1024; // 1MB
    }
}

// 消息类
class Message implements Serializable {
    public static final int REGISTER = 1;
    public static final int TEXT = 2;
    public static final int IMAGE = 3;
    public static final int ERROR = 4;
    
    private static final long serialVersionUID = 1L;
    
    private int type;
    private String senderId;
    private String receiverId;
    private Object content;
    private String context;

    public Message(int type, String senderId, String receiverId, Object content) {
        this.type = type;
        this.senderId = senderId;
        this.receiverId = receiverId;
        this.content = content;
    }

    public int getType() {
        return type;
    }

    public String getSenderId() {
        return senderId;
    }

    public String getReceiverId() {
        return receiverId;
    }
    public String  getContext() {
        return context;
    }

    public Object getContent() {
        return content;
    }
}